package org.jfonia.musicxml;

import org.jfonia.util.JFoniaException;
import org.w3c.dom.Node;

//TODO: wrap exceptions such as NumberFormatException...

/**
 * Used for exceptions during import (parsing) of MusicXML-document.
 * Note: also used for warnings - in that case the exception is not thrown.
 */
public class MusicXMLImportException extends JFoniaException {
	private static final long serialVersionUID = 3806770138687244267L;
	
	protected Node node  = null;

	/**
	 * Construct a MusicXMLImportException using given message, param and node.
	 * @param code must be non null
	 * @param node optional MusicXML DOM document node to which this exception pertains (may be null)
	 */
	public MusicXMLImportException(String message, Node node) {
		super(message);
		this.node = node;
	}

	/**
	 * Construct a MusicXMLImportException using given message, param and node.
	 * @param code must be non null
	 * @param cause exception which caused this exception
	 * @param node optional MusicXML DOM document node to which this exception pertains (may be null)
	 */
	public MusicXMLImportException(String message, Throwable cause, Node node) {
		super(message, cause);
		this.node = node;
	}

	public Node getNode()
	{
		return node;
	}
	
	public void setNode(Node node)
	{
		this.node = node;
	}

	@Override
	public String toString()
	{
		return super.getMessage() + getPositionInfo(node);
	}
	
	/**
	 * Returns a readable message giving location information about the xml-node,
	 * i.e. the line number where the node starts and the id (number) of
	 * the (enclosing) measure.
	 */
	protected static String getPositionInfo(Node node) {
		StringBuffer sb = new StringBuffer(" in xml-node");

		Node measureNode = node;
		while (measureNode != null && !measureNode.getNodeName().equals("measure"))
			measureNode = measureNode.getParentNode();
		if (measureNode != null)
		{
			String numStr = SimpleDOMParser.findAttribute(measureNode, "number");
			if (numStr != null)
			{
				sb.append(" in measure ");
				sb.append(numStr);
			}
		}
		
		if (node != null)
		{
			sb.append(" in xml-element <");
			sb.append(node.getNodeName());
			sb.append("> starting at line ");
			sb.append(SimpleDOMParser.getStartLine(node));
		}
		
		return sb.toString();		
	}

	
}
